﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;
using ResourceLoadBalancer.WebServices.Contracts.Data;
using System.Net;
using System.Security.AccessControl;
using System.Security.Principal;
using ResourceLoadBalancer.WebServices.Clients.Helpers;
using Microsoft.Samples.SqlServer;

namespace ResourceLoadBalancer.Client
{
    public class FileSystemScanner : FileScanner
    {

        IList<ResourceURIDataContract> resourceURIs = null;

        private static int BATCH_SIZE = 100;
        private static string FILE_SYSTEM_QUEUE_TYPE = "FileSystem";

        public FileSystemScanner()
        {
            this.resourceURIs = new List<ResourceURIDataContract>();
        }

        public IList<ResourceURIDataContract> ResourceURIs
        {
            get { return resourceURIs; }
            set { resourceURIs = value; }
        }

        public void ConfigureQueuing(string queueName)
        {
            this.queueName = queueName;
            base.ConfigureQueuing(FILE_SYSTEM_QUEUE_TYPE, queueName);
        }

        

        public void GetFiles(string directory)
        {
            ResourceURIDataContract resourceURI = new ResourceURIDataContract();
            
            try
            {
                foreach (string f in Directory.GetFiles(directory, "*.*"))
                {
                    FileInfo fileInfo = new FileInfo(f);
                    resourceURI = new ResourceURIDataContract();
                    
                    resourceURI.URI = fileInfo.FullName;
                    QueueResourceURI(resourceURI);
                    Console.WriteLine("Queued: " + resourceURI.URI);
                    
                }

                foreach (string d in Directory.GetDirectories(directory))
                {
                    GetFiles(d);
                }
            }
            catch (System.Exception excpt)
            {
                Console.WriteLine(excpt.Message);
            }
        }

        public void QueueResourceURI(ResourceURIDataContract resourceURI)
        {
            resourceURIs.Add(resourceURI);

            if (resourceURIs.Count == BATCH_SIZE)
            {
                SubmitResources();
            }
        }

        public void SubmitResources()
        {
            int batchSize = 100;
            int currentBatchSize = 0;
            int batchCount = 0;

            IList<ResourceDataContract> resourceBatch = new List<ResourceDataContract>();
            IList<ResourceURIDataContract> resourceURIBatch = new List<ResourceURIDataContract>();

            
            currentBatchSize = 0;
            batchCount = 0;

            Console.WriteLine("Processing resources URI");

            for (int i = 0; i < resourceURIs.Count; i++)
            {
                if (currentBatchSize < batchSize)
                {
                    resourceURIBatch.Add(resourceURIs[i]);
                    currentBatchSize++;
                }
                else if (currentBatchSize == batchSize)
                {
                    batchCount++;
                    Console.Write("Sending batch #" + batchCount + "...");
                    serviceClient.QueueFileSystemResourceURIs(hostName, queueName, resourceURIBatch);
                    Console.Write("Done!\n");
                    currentBatchSize = 0;
                    resourceURIBatch.Clear();
                }
            }
            if (resourceURIBatch.Count > 0)
            {
                batchCount++;
                Console.Write("Sending batch #" + batchCount + "...");
                serviceClient.QueueFileSystemResourceURIs(hostName, queueName, resourceURIBatch);
                Console.Write("Done!\n");
                resourceURIBatch.Clear();
                
            }
            resourceURIs.Clear();
        }

        public void ScanResources(string path)
        {
            //MD5Utility md5Utility = new MD5Utility();
            if (serviceClient.IsServiceAvailable())
            {
                base.CleanResourceURIs(path);
                GetFiles(path);
                SubmitResources();
            }
            else
            {
                Console.WriteLine("Service unavailable");
            }
            /*
            //foreach(FileInfo file in FilesInfo)
            Parallel.ForEach(FilesInfo, file =>
            {
                ResourceLoadBalancerServiceClientHelper resourceLoadBalancerServiceClientHelper = new ResourceLoadBalancerServiceClientHelper();
                //ResourceDataContract resource = new ResourceDataContract();
                ResourceURIDataContract resourceURI = new ResourceURIDataContract();
                string owner = "";

                resourceURI.URI = file.FullName;
                resourceURI.HostName = hostName;
                
                resourceURI.URIHash = md5Utility.CalculateMD5Hash(file.FullName);

                try
                {
                    FileSecurity fsec = file.GetAccessControl(AccessControlSections.Owner);

                    owner = fsec.GetOwner(typeof(System.Security.Principal.NTAccount)).Value;
                }
                catch (Exception)
                {
                    owner = "unavailable";
                }

                resourceURI.Owner = owner;
                resourceURI.LastModifiedDate = file.LastWriteTime;
                resourceURI.CreatedDate = file.CreationTime;
                resourceURI.InventoryDate = DateTime.Now;
                
                try
                {
                //    ResourceURIDataContract existingResourceURI = resourceLoadBalancerServiceClientHelper.GetResourceURI(resourceURI);

                //    if (existingResourceURI.LastModifiedDate == resourceURI.LastModifiedDate)
                //    {
                        ResourceDataContract resource = md5Utility.CalculateMD5Hash(file);
                        resourceURI.ResourceHash = resource.Hash;
                        Resources.Add(resource);
                        ResourcesURI.Add(resourceURI);
                //    }

                }
                catch (Exception ex)
                {

                    Console.Write(ex.Message);
                }
            }
            );*/
        }
    }
}
